/*
 * This file is part of the <a href="http://code.google.com/p/pux">PUX Framework</a>
 *
 * Copyright 2008 by <a href="mailto:jfendler@polytechnic.edu.na">Jens Fendler</a>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package de.teamskill.pux.library.net;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;

import de.teamskill.pux.engine.DataElement;
import de.teamskill.pux.engine.AbstractNode;
import de.teamskill.pux.engine.OutputPort;

/**
 * HttpInputNode
 * 
 * @author <a href="mailto:jfendler@polytechnic.edu.na">Jens Fendler</a>
 * 
 */
public class HttpInputNode extends AbstractNode {

	/**
	 * out
	 */
	private OutputPort out;

	/**
	 * uri
	 */
	private String uri;

	/**
	 * proxyPort
	 */
	private int proxyPort;

	/**
	 * proxyHost
	 */
	private String proxyHost;

	/**
	 * proxyUser
	 */
	private String proxyUser;

	/**
	 * proxyPass
	 */
	private String proxyPass;

	/**
	 * HttpInputNode Constructor
	 * 
	 */
	public HttpInputNode(String uri) {
		this("HTTPInput" + nr++, uri, false);
	}

	/**
	 * HttpInputNode Constructor
	 * 
	 * @param name
	 * @param continuous
	 */
	public HttpInputNode(String name, String uri, boolean continuous) {
		super(name, continuous);
		setUri(uri);
	}

	/**
	 * setProxy
	 * 
	 * @param proxyHost
	 * @param proxyPort
	 */
	public void setProxy(String proxyHost, int proxyPort) {
		setProxy(proxyHost, proxyPort, null, null);
	}

	/**
	 * setProxy
	 * 
	 * @param proxyHost
	 * @param proxyPort
	 * @param proxyUser
	 * @param proxyPassword
	 */
	public void setProxy(String proxyHost, int proxyPort, String proxyUser, String proxyPassword) {
		this.proxyHost = proxyHost;
		this.proxyPort = proxyPort;
		this.proxyUser = proxyUser;
		this.proxyPass = proxyPassword;
	}

	/**
	 * @see de.teamskill.pux.engine.AbstractNode#compute()
	 */
	public void compute() {
		HttpClient client = new HttpClient();

		// prepare for the use of a proxy server (with optional authentication)
		if (proxyHost != null && proxyPort > 0) {
			client.getHostConfiguration().setProxy(proxyHost, proxyPort);
			if (proxyUser != null) {
				if (proxyPass == null) {
					proxyPass = "";
				}
				AuthScope authscope = new AuthScope(proxyHost, proxyPort);
				Credentials credentials = new UsernamePasswordCredentials(proxyUser, proxyPass);
				client.getState().setProxyCredentials(authscope, credentials);
			}
		}

		HttpMethod m = new GetMethod(uri);
		m.setFollowRedirects(true);
		try {
			int responseCode = client.executeMethod(m);
			String body = m.getResponseBodyAsString();
			DataElement de = new DataElement(body);
			de.annotate("http.responsecode", new Integer(responseCode));
			for (Header h : m.getResponseHeaders()) {
				de.annotate(h.getName(), h.getValue());
			}
			out.pushBuffer(de);
		} catch (Exception e) {
			// TODO possibly re-try the connection n-times
			LOG_NODE.severe("Failed to get " + uri + ": " + e.getLocalizedMessage());
		}
	}

	/**
	 * JavaBean-style getter-method for out
	 * 
	 * @return the out
	 */
	public OutputPort getOut() {
		return out;
	}

	/**
	 * /** JavaBean-style setter-method for out
	 * 
	 * @param out
	 *            the out to set
	 */
	public void setOut(OutputPort out) {
		this.out = out;
	}

	/**
	 * JavaBean-style getter-method for uri
	 * 
	 * @return the uri
	 */
	public String getUri() {
		return uri;
	}

	/**
	 * /** JavaBean-style setter-method for uri
	 * 
	 * @param uri
	 *            the uri to set
	 */
	public void setUri(String uri) {
		this.uri = uri;
	}

	/**
	 * @see de.teamskill.pux.engine.AbstractNode#createPorts()
	 */
	protected void createPorts() {
		out = addOutputPort(new OutputPort("OUT", this));
	}

}
